Hi Dai Gei Ho~ 我是Winnie ~ 延續昨的主題,我們介紹了Service Worker的運作,接著此篇文章中我們要透過簡單實作離線快取進一步的了解Service Worker生命週期及 fetch攔截請求 的應用。
在昨天文章中我們有提到,如要在網站中使用 Service Worker 需透過navigator.serviceWorker.register
方法進行註冊,而此方法為一個Promise,可以捕獲成功失敗來進行下ㄧ步處理。
同時在註冊 Service Worker 時,需注意註冊檔案的存放路徑
,因為存放的位置 會決定 Service Worker的 作用範圍。
舉例來說:
如將sw.js
放置於example.com/
根目錄下,此時 service worker 即可存取資料的範圍為example.com/
中的資料,
相反地,如果example.com/users/index.html
,就無法進行存取。
// main.js
if('serviceWorker' in navigator ){
navigator.serviceWorker.register("/sw.js")
.then( registration => {
// console.log('SW is reqistration', registration)
})
.catch( err => console.log('SW reqistration failed :', err))
} else {
console.log('Sw is not supported!')
}
雖然在各Browser中針對service worker大多都已經支援,但為了以防萬一,我們可以在註冊前來檢查 Browser中 是否支援,減少Browser中的記憶體資源消耗。
在註冊成功後,在Service Worker 中會觸發 install 事件,透過event.waitUntil()來延長install 事件
此時我們就可以進行靜態資源快取,接著,使用caches.open()
設置一個cache的空間將需要cache的資料,透過cache.addAll(Array)
或著 cache.add(String)
來儲存。
caches.add(String) 、cache.addAll(Array) 為 新增 cache
let version ='V1';
self.addEventListener('install', e => {
console.log('SW is install!');
e.waitUntil(
caches.open(version).then(cache => cache.addAll([
"/", "index.html" , "main.js", "main.css"
]))
);
});
透過Fetch事件攔截 https 請求,如果再cach中有緩存目前相請求資料就是 return 目前快取的資源,沒有就進行原本的請求。
caches.match 為 查詢 cache
self.addEventListener('fetch', (e)=>{
e.respondWith(caches.match(e.request).then(res =>{
if (res) {
return res
} else {
return fetch(event.request)
}
})
咦?那有些資源不是馬上會使用到,沒有全部進快取 怎麼辦?
此時可以透過fetch 事件觸發時的方法,將一開始沒有快取的資源 cache.put()
放入原本定義的cache版本中。
//略..
fetch(event.request)
.then((es=>{
caches.open(version)
.then((cache)=>{
cache.put(e.request.url, res.clone());
return res;
})
});
但你知道的,不管什麼事總會有變變變的時候
假設快取新增了不同版本,造成新舊快取同時存在,此時在抓取相同資源時,就會遇到有版本的問題。
所以我們可以透過 Service Worker中的sw.js每次都會被執行的特性,更新 快取版本。
let version ='V2';
self.addEventListener('install', e => {
console.log('SW is install!');
e.waitUntil(
caches.open(version).then(cache => cache.addAll([
"/", "index.html" , "main.js", "main.css"
]))
);
this.skipWaiting()
});
self.addEventListener('activate', e => {
console.log("activate")
let delFn = caches.keys().then((cacheList) => {
return Promise.all(
cacheList.map((cacheName)=>{
if (cacheName !== verson) {
return caches.delete(cacheName);
}
})
);
})
e.waitUntil(Promise.all([delFn])
.then(() => {
return self.clients.claim()
})
)
});
透過在install事件中調用 self.skipWaiting()方法,直接觸發當activate 事件,進行快取版本的比對,如果cache 名字 與 新版不符,就進行刪除,最後使用self.clients.claim()
更新快取。
以上就是關於 Service Worker 常見功能 離線緩存 實作介紹(呼,而在下篇文章中將繼續來介紹 Service Worker 另一個常見功能 訂閱推播 (本來是預計一篇文章,但真的說不完。
那今天文章先到這邊了,謝謝願意花時間看此篇文章的你,如果文章有錯誤的地方,再麻煩不吝嗇的給予指教,感謝!!
每日有感而發:
今天想分享一首每天一定會聽的歌 -> OKDAL - Hero 히어로
每當聽到這首歌 就會想到 一個人在韓國七天的那段時間
不用跟任何人說話 走啊走啊走的 好平靜